package Absyn;

import java.util.ArrayList;
import java.util.List;

import record.Schema;
import parse.ModifyData;
import parse.QueryData;
import query.*;
import parse.*;

public class Data {
	  List<Term> terms = new ArrayList<Term>();
	  public Data(){}
	  
	  public Object prStmList(StmList e) {
		  if(e.statement instanceof SelectExp)
			  return prExp((SelectExp)e.statement);
		  else if(e.statement instanceof IndexExp)
	    	  return prExp((IndexExp)e.statement);
	      else if(e.statement instanceof ViewExp)
	    	  return prExp((ViewExp)e.statement);
	      else{
			  return prExp((TabExp)e.statement);
	      }
	  }
	  
	  QueryData prExp(SelectExp e) {
			OutputExp output = (OutputExp)e.outputOption;
			AttriList fields = e.attributes;
			int source_type = 0;
			TabList tablist = null;
			Exp source = null;
			if(e.source instanceof TabList){
				tablist = (TabList)e.source;
			}
			else if(e.source instanceof TabOpExp){
				source = (TabOpExp)e.source;
			}
			else if(e.source instanceof SelectExp){
				source = (SelectExp)e.source;
			}
			else
				throw new Error("Print.prExp.SelectExp");
			Predicate pred=null; GroupExp gexp=null; OrderExp oexp=null;
			if(e.condition!= null){
				prExp((IfExp)(((MulCondiExp)e.condition).conditions));
				pred = new Predicate((IfExp)(((MulCondiExp)e.condition).conditions), terms);
				gexp = (GroupExp)((MulCondiExp)e.condition).group;
				oexp = (OrderExp)((MulCondiExp)e.condition).order;
			}
			return new QueryData(output, fields, tablist, source, pred, gexp, oexp);
	  }
	  
	  List<String> prAttriList(AttriList e) {
		  List<String> list = new ArrayList<String>();
		  while (e!=null){
			  list.add(((AttriExp)e.attribute).attribute.toString());
			  e = e.tail;
		  }
		  return list;
	  }
	  
	  Object prExp(TabExp e) {
		   if(e instanceof CreaExp)
			   return prExp((CreaExp)e);
		   else if(e instanceof AltExp)
			   return prExp((AltExp)e);
		   else if(e instanceof DelExp)
			   return prExp((DelExp)e);
		   else if(e instanceof InsertExp)
			   return prExp((InsertExp)e);
		   else if(e instanceof DropExp)
			   return prExp((DropExp)e);
		   else if(e instanceof UpdateExp)
			   return prExp((UpdateExp)e);
		   else
			   throw new Error("Print.prExp.TabExp");
	  }
	  
	  void prExp(IfExp e){
		  if(e.test instanceof IfExp)
			  prExp((IfExp)e.test);
		  else if(e.test instanceof CondiExp)
			  prExp((CondiExp)e.test);
		  if(e.thenclause instanceof IfExp)
			  prExp((IfExp)e.thenclause);
		  else if(e.thenclause instanceof CondiExp)
			  prExp((CondiExp)e.thenclause);
		  if (e.elseclause!=null) {
			  if(e.elseclause instanceof IfExp)
				  prExp((IfExp)e.elseclause);
			  else if(e.elseclause instanceof CondiExp)
				  prExp((CondiExp)e.elseclause);
		  }
	  }
	  
	  /*Predicate prCondiList(CondiList e) {
		  Predicate pred = new Predicate();
		  List<List<Term>> condi = new ArrayList<List<Term>>();
		  List<Term> terms = new ArrayList<Term>();
		  while (e!=null){
			  Term term = prExp((CondiExp)e.condition);
			  if(e.type==CondiList.NONE || e.type==CondiList.AND){
				  terms.add(term);
				  
			  }
			  if(e.type==CondiList.OR){
				  condi.add(terms);
				  terms = new ArrayList<Term>(); 
				  terms.add(term);
			  }
			  if(e.tail==null)
				  condi.add(terms);
		      e = e.tail;
		  }
		  return pred;
	  }*/
	  
/*	  Term prExp(CondiExp e) {
		  if(e.type==CondiExp.EXIST)
			  return new Term(e.type, e.select);
		  else if(e.type==CondiExp.EQ || e.type==CondiExp.NEQ ||e.type==CondiExp.LT 
				  ||e.type==CondiExp.LE ||e.type==CondiExp.GT ||e.type==CondiExp.GE){
			  return new Term(e.type, e.attr1, e.attr2);
		  }
		  else if(e.type==CondiExp.BETWEEN) {
			  return new Term(e.type, e.attr1, e.attr2, e.attr3);
		  }
		  else if(e.type==CondiExp.IN){
			  return new Term(e.type, e.attr1, e.vl);
		  }
		  else
			  throw new Error("Print.prExp.CondiExp3");
	  }*/

	  
	  void prExp(CondiExp e) {
		  if(e.type==CondiExp.EXIST)
			  terms.add(new Term(e.type, e.select));
		  else if(e.type==CondiExp.EQ || e.type==CondiExp.NEQ ||e.type==CondiExp.LT 
				  ||e.type==CondiExp.LE ||e.type==CondiExp.GT ||e.type==CondiExp.GE){
			  terms.add(new Term(e.type, e.attr1, e.attr2));
		  }
		  else if(e.type==CondiExp.BETWEEN) {
			  terms.add(new Term(e.type, e.attr1, e.attr2, e.attr3));
		  }
		  else if(e.type==CondiExp.IN){
			  terms.add(new Term(e.type, e.attr1, e.vl));
		  }
		  else
			  throw new Error("Print.prExp.CondiExp3");
	  }
	  Object prExp(UpdateExp e) {
			String tblname = e.table.name;
			SetList temp;	int i=0;
			AttriList fldname=null, temp_a=null;
			ValList newval=null, temp_v=null;
			if ((temp=e.setList)!=null) {
				  if(i==0){
					  fldname = new AttriList(0, temp.attribute, null);
					  newval = new ValList(0, temp.value, null);
					  temp_a=fldname;
					  temp_v=newval;
					  i=1;
				  }
				  temp_a.tail = new AttriList(0, temp.attribute, null);
				  temp_a = temp_a.tail;
				  temp_v.tail = new ValList(0, temp.value, null);
				  temp_v = temp_v.tail;
			}
			prExp((IfExp)e.conditions);
			Predicate pred = new Predicate((IfExp)e.conditions, terms);
		    return new ModifyData(tblname, fldname, newval, pred);
	  }
	  
	  Object prExp(DelExp e) {
			String tblname = e.table.name;
			prExp((IfExp)e.conditions);
			Predicate pred = new Predicate((IfExp)e.conditions, terms);
		  	return new DeleteData(tblname, pred);
	  }
	  
	  Object prExp(InsertExp e) {
			String tblname = e.table.name;
			List<String> flds = prAttriList(e.attributes);
			List<Exp> vals = prValList(e.values);
		    return new InsertData(tblname, flds, vals);
	  }
	  
	  List<Exp> prValList(ValList e) {
		  List<Exp> list = new ArrayList<Exp>();
		  while (e!=null) {
		      list.add(e.value);
		      e= e.tail;
		  }
		  return list;
	  }
	  
	  Object prExp(CreaExp e) {
			String tblname = e.table.name;
			Schema sch = prNewList(e.newList);
		    return new CreateTableData(tblname, sch);
	  }
	  
	  Schema prNewList(NewList e) {
		  Schema sch = new Schema();
		  while (e!=null) {
			  sch.addField(e.attribute.toString(), e.type.type, e.type.len);
			  e = e.tail;
		  }
		  return sch;
	  }
	  
	  Object prExp(AltExp e) {
		    String tblname = e.table.name;
		    NewList newlist = null;
		    String delField = null;
		    if(e.type==1)
		    	newlist = e.newlist;
		    else
		    	delField = e.delAttri.name;
		    return new AlterTableData(tblname, newlist, delField);
	  }
	  
	  Object prExp(DropExp e) {
		   return new DropTableData(e.table.name);
	  }
	  
	  Object prExp(IndexExp e) {
		   if(e instanceof CreaIndexExp)
			   return prExp((CreaIndexExp)e);
		   else if(e instanceof DropIndexExp)
			   return prExp((DropIndexExp)e);
		   else
			   throw new Error("Print.prExp.IndexExp");
	  }
	  
	  Object prExp(CreaIndexExp e){
		  	String vwname = e.index_name.name;
		    String tblname = e.table_name.name;
		    List<String> fldname = prAttriList(e.attributes);
		    return new CreateIndexData(vwname, tblname, fldname);
	  }
	  
	  Object prExp(DropIndexExp e){
		  	String vwname = e.index_name.name;
		  	String tblname = e.table_name.name;
		    return new DropIndexData(vwname, tblname);
	  }
	  
	  Object prExp(ViewExp e) {
		   if(e instanceof CreaViewExp)
			   return prExp((CreaViewExp)e);
		   else if(e instanceof DropViewExp)
			   return prExp((DropViewExp)e);
		   else
			   throw new Error("Print.prExp.ViewExp");
	  }
	  
	  Object prExp(CreaViewExp e){
		  	String viewname = e.view_name.name;
		    QueryData qrydata = prExp((SelectExp)e.selExp);
		    return new CreateViewData(viewname, qrydata);
	  }
	  
	  Object prExp(DropViewExp e){
		  	String viewname = e.view_name.name;
		    return new DropViewData(viewname);
	  }
}
